import java.awt.Point;
import java.util.ArrayList;

public class MapUtils {

	public static Point getSpaceToPut(MapObject[][] world, Point near) {
		if (world[near.y][near.x].getType() == MapObjectType.EMPTY_SPACE) {
			return (Point) near.clone();
		}
		if (isWorldFull(world)) {
			Main.quit();
		}
		return findEmptySpace(world,near);
	}

	public static Point getAdjecentPoint(Point point, Direction direction) {
		Point p = null;
		switch (direction) {
		case LEFT:
			p = new Point(point.x - 1, point.y);
			break;
		case RIGHT:
			p = new Point(point.x + 1, point.y);
			break;
		case UP:
			p = new Point(point.x, point.y - 1);
			break;
		case DOWN:
			p = new Point(point.x, point.y + 1);
			break;
		}
		try {
			@SuppressWarnings("unused")
			MapObject wo = Main.getMap().getMap()[p.y][p.x];
		} catch (IndexOutOfBoundsException ioobe) {
			return point;
		}
		return p;
	}

	public static MapObject getAdjecentObject(Point point, Direction direction) {
		Point p = null;
		switch (direction) {
		case LEFT:
			p = new Point(point.x - 1, point.y);
			break;
		case RIGHT:
			p = new Point(point.x + 1, point.y);
			break;
		case UP:
			p = new Point(point.x, point.y - 1);
			break;
		case DOWN:
			p = new Point(point.x, point.y + 1);
			break;
		}
		try {
			MapObject wo = Main.getMap().getMap()[p.y][p.x];
			return wo;
		} catch (IndexOutOfBoundsException ioobe) {
			return null;
		}
	}

	private static boolean isWorldFull(MapObject[][] world) {
		for (MapObject[] wot : world) {
			for (MapObject wo : wot) {
				if (isOneOfFacilities(wo)) {
					return false;
				}
			}
		}
		return true;
	}

	private static boolean isOneOfFacilities(MapObject wo) {
		if (wo.getType() == MapObjectType.EMPTY_SPACE) {
			return true;
		} else if (wo.getType() == MapObjectType.Tree) {
			return true;
		} else if (wo.getType() == MapObjectType.PowerPlant) {
			return true;
		}
		return false;
	}

	@SuppressWarnings("unused")
	private static ArrayList<Point> getAdjecentPoints(MapObject[][] world, Point p) {
		ArrayList<Point> points = new ArrayList<Point>();
		try {
			MapObject wo = world[p.y - 1][p.x - 1];
			points.add(new Point(p.x - 1, p.y - 1));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y - 1][p.x];
			points.add(new Point(p.x, p.y - 1));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y - 1][p.x + 1];
			points.add(new Point(p.x + 1, p.y - 1));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y][p.x + 1];
			points.add(new Point(p.x + 1, p.y));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y + 1][p.x + 1];
			points.add(new Point(p.x + 1, p.y + 1));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y + 1][p.x];
			points.add(new Point(p.x, p.y + 1));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y + 1][p.x - 1];
			points.add(new Point(p.x - 1, p.y + 1));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		try {
			MapObject wo = world[p.y][p.x - 1];
			points.add(new Point(p.x - 1, p.y));
		} catch (IndexOutOfBoundsException ioobe) {
			// do nothing
		}
		return points;
	}

	private static Point findEmptySpace(MapObject[][] world,Point p) {
		ArrayList<Point> points = getAdjecentPoints(world, p);
		for (Point po : points) {
			if (world[po.y][po.x].getType() == MapObjectType.EMPTY_SPACE) {
				return po;
			}
		}
		for (Point po : points) {
			return findEmptySpace(world,po);
		}
		return null;
	}
}
